﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using PcapDotNet.Core;
using PcapDotNet.Packets;
using PcapDotNet.Packets.IpV4;

namespace NetMon
{
    public partial class MainWindow : Form
    {
        private PacketCommunicator communicator = null;

        class Host : IComparable<Host>
        {
            public Host()
            {
                Source = new IpV4Address(0);
                Value = 0 ;
            }
            public uint Addr() { uint addr = Source.ToValue(); return (addr > 0 ? addr : uint.MaxValue); }
            public IpV4Address Source { get; set; }
            public int Value { get; set; }
            public string Proto { get; set; }

            public void Ping(IpV4Address newSource, string proto)
            {
                Source = newSource;
                Value = 100;
                Proto = proto;
            }

            public void Update()
            {
                if (Value > 0)
                    Value = Value - 1;
                else
                {
                    Source = new IpV4Address(0);
                    Value = -1;
                    Proto = "";
                }
            }

            public int CompareTo(Host rhs)
            {
                return Addr().CompareTo(rhs.Addr());
            }
        }

        class Display
        {
            public Display(System.Windows.Forms.Label label, System.Windows.Forms.ProgressBar progress)
            {
                Label = label;
                Progress = progress;
            }

            public System.Windows.Forms.Label Label { get; set; }
            public System.Windows.Forms.ProgressBar Progress { get; set; }

            public void Update(Host host)
            {
                if (host.Source.ToValue() == 0 || host.Value < 0)
                {
                    Label.Text = "";
                    Progress.Value = 0;
                    Progress.Visible = false;
                }
                else
                {
                    if (Progress.Visible == false)
                    Progress.Visible = true;
                    Label.Text = host.Proto[0] + host.Source.ToString();
                    Progress.Value = host.Value;
                }
            }
        }
        private List<Host> hosts;
        private List<Display> displays;

        public MainWindow(string deviceName, PacketCommunicator comm)
        {
            InitializeComponent();
            int n = deviceName.IndexOf('\'');
            if (n > 0)
                deviceName = deviceName.Remove(0, n);

            communicator = comm;

            hosts = new List<Host>(new Host[7] { new Host(), new Host(), new Host(), new Host(), new Host(), new Host(), new Host() });
            displays = new List<Display>(new Display[7] {
                new Display(this.label1, this.progressBar1),
                new Display(this.label2, this.progressBar2),
                new Display(this.label3, this.progressBar3),
                new Display(this.label4, this.progressBar4),
                new Display(this.label5, this.progressBar5),
                new Display(this.label6, this.progressBar6),
                new Display(this.label7, this.progressBar7)
            });
        }

        private void tmrRefresh_Tick(object sender, EventArgs e)
        {
            foreach (Host host in hosts)
            {
                host.Update();
            }
            hosts.Sort();

            if (communicator != null)
                GetPackets();

            hosts.Sort();

            for (var i = 0; i < displays.Count; ++i)
            {
                displays[i].Update(hosts[i]);
            }
        }

        private void GetPackets()
        {
            Packet packet;
            while (true)
            {
                PacketCommunicatorReceiveResult result = communicator.ReceivePacket(out packet);
                if (result != PacketCommunicatorReceiveResult.Ok)
                    break;

                IpV4Datagram dgram = packet.Ethernet.IpV4;
                IpV4Address addr = dgram.Source;
                string proto = dgram.Protocol.ToString();

                bool found = false;
                foreach (Host host in hosts)
                {
                    if (host.Source == addr || host.Source.ToValue() == 0)
                    {
                        host.Ping(addr, proto);
                        hosts.Sort();
                        found = true;
                        break;
                    }
                }

                if (found == false)
                {
                    Host host = new Host();
                    host.Ping(addr, proto);
                    hosts.Add(host);
                    hosts.Sort();
                }
            }
        }
    }
}
